package com.dksidana.java.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.dksidana.java.jdbc.bean.BeanHandler;
import com.dksidana.java.jdbc.core.ResultSetHandler;

public class JDBCUtils{

	public static void fillStatement(PreparedStatement preparedStatement,Object... args) throws SQLException
	{
		int parameterIndex=1;
		for(Object object:args)
		{
			preparedStatement.setObject(parameterIndex++,object);
		}
	}
	public static int fillStatementAndExecuteUpdate(PreparedStatement preparedStatement,Object... args) throws SQLException
	{
		fillStatement(preparedStatement, args);
		return preparedStatement.executeUpdate();
	}
	public static ResultSet fillStatementAndExecuteQuery(PreparedStatement preparedStatement,Object... args) throws SQLException
	{
		fillStatement(preparedStatement, args);
		return preparedStatement.executeQuery();
	}

	public static void closeResultSetQuietly(ResultSet resultSet)
	{
		if(resultSet!=null)
		{
			try {
				resultSet.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void closeStatementQuietly(Statement statement,String query)
	{
		if(statement!=null)
		{
			try
			{
				statement.close();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	public static void closeStatementAndResultSetQuietly(Statement statement,ResultSet resultSet,String query)
	{
		closeResultSetQuietly(resultSet);
		closeStatementQuietly(statement, query);
	}
	/**
	 * Note: this closes resultSet after converting it to object
	 * @param <T>
	 * @param resultSetHandler
	 * @param resultSet
	 * @return
	 * @throws DBException
	 */
	public static <T> T getObject(ResultSetHandler<T> resultSetHandler,ResultSet resultSet) throws SQLException
	{
		try
		{
			if(resultSet.next())
			{
				return resultSetHandler.handleResultSet(resultSet);
			}
			else
			{
				return null;
			}			
		}
		finally
		{
			closeResultSetQuietly(resultSet);
		}
	}
	/**
	 * Executes the given preparedStatement, get the result Set, convert it to object and closes the resultSet
	 * @param <T>
	 * @param query
	 * @param resultSetHandler
	 * @param preparedStatement
	 * @return
	 * @throws DBException
	 */
	public static <T> T getObject(ResultSetHandler<T> resultSetHandler,String query,PreparedStatement preparedStatement) throws SQLException
	{
		ResultSet resultSet=preparedStatement.executeQuery();
		return getObject(resultSetHandler,resultSet);
	}
	public static <T> ArrayList<T> getObjectList(ResultSetHandler<T> resultSetHandler,String query,PreparedStatement preparedStatement) throws SQLException
	{
		ResultSet resultSet=preparedStatement.executeQuery();
		return getObjectList(resultSetHandler,resultSet);
	}
	/**
	 * Note: this closes resultSet after converting it to object list
	 * @param <T>
	 * @param resultSetHandler
	 * @param resultSet
	 * @return
	 * @throws DBException
	 */
	public static <T> ArrayList<T> getObjectList(ResultSetHandler<T> resultSetHandler,ResultSet resultSet) throws SQLException
	{
		ArrayList<T> list=new ArrayList<T>();
		try
		{
			while(resultSet.next())
			{
				list.add(resultSetHandler.handleResultSet(resultSet));
			}
			return list;
		}
		finally
		{
			closeResultSetQuietly(resultSet);
		}
	}
	
	
	/**
	 * create statement,Execute query, Create object using resultSetHandler,close resultSet and statement.
	 * @param <T>
	 * @param connection
	 * @param query
	 * @param resultSetHandler
	 * @return
	 * @throws SQLException
	 */
	public static <T> T executeQuery(Connection connection,String query, ResultSetHandler<T> resultSetHandler) throws SQLException
	{
		Statement s=null;
		ResultSet resultSet=null;
		T o=null;
		try
		{
			s=connection.createStatement();
			resultSet=s.executeQuery(query);
			o=resultSetHandler.handleResultSet(resultSet);
		}
		finally
		{
			if(resultSet!=null)
				resultSet.close();
			if(s!=null)
				s.close();	
		}
		return o;
	}
	public static int executeUpdate(Connection connection,String query) throws SQLException
	{
		Statement s=null;
		ResultSet resultSet=null;
		int result=0;
		
		try
		{
			s=connection.createStatement();
			result=s.executeUpdate(query);
			
		}
		finally
		{
			if(resultSet!=null)
				resultSet.close();
			if(s!=null)
				s.close();	
		}
		return result;
	}
	
	public static <T> T getObject(Connection connection,String query, Class<T> beanClass) throws SQLException
	{
		//return executeQuery(connection, query, new BeanResultSetHandler<T>(beanClass));
		Statement s=null;
		ResultSet resultSet=null;
		T o=null;
		try
		{
			s=connection.createStatement();
			resultSet=s.executeQuery(query);
			o=BeanHandler.toBean(resultSet,beanClass);
		}
		finally
		{
			if(resultSet!=null)
				resultSet.close();
			if(s!=null)
				s.close();	
		}
		return o;
	}
	public static <T> List<T> getObjectList(Connection connection,String query, Class<T> beanClass) throws SQLException
	{
		//return executeQuery(connection, query, new BeanArrayResultSetHandler<T>(beanClass));
		Statement s=null;
		ResultSet resultSet=null;
		List<T> o=null;
		try
		{
			s=connection.createStatement();
			resultSet=s.executeQuery(query);
			o=BeanHandler.toBeanList(resultSet,beanClass);
		}
		finally
		{
			if(resultSet!=null)
				resultSet.close();
			if(s!=null)
				s.close();	
		}
		return o;
	}
}
